package com.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
//--------------------circular view path问题--------------
@Controller
@RequestMapping("/circular")
public class CircularViewController {

    @RequestMapping("/d")
    public void defaultView() {
        // 配置类不配置任何的视图解析器 ，启动程序后访问/d就会触发循环引用视图的异常

        // 注意：不配置任何视图解析器，mvc框架默认也有一个视图解析器的，就是InternalResourceViewResolver

        //在DispatcherServlet.doDispatch的方法里有调用applyDefaultViewName方法来设置默认视图名
        // 默认视图名的获取逻辑就是当前请求地址，这里的话默认视图名就是d,不是方法名

        System.out.println("default view name---");
    }

    @RequestMapping("/c")
    public String c() {
        // 当遇到“Circular view path”异常时，通常意味着视图解析器（ViewResolver）遇到了一个循环路径问题。
        // 这个问题通常发生在视图名称和请求路径名称相同时
        // 见源码的 UrlBasedViewResolver.createView()与InternalResourceView.prepareForRendering
        // 为什么这是一个问题，是因为返回的视图名，默认渲染逻辑是转发到这个jsp，也就是从DispatcherServlet转发到jsp
        // 而mvc又有另一个情况，就是控制器方法返回值是"forward:"开头的是转发到另一个控制器方法
        // 那万一控制器方法返回的是"forward:当前请求方法的地址",到底是转发到视图呢还是又转发回当前这个控制器方法呢？
        // 这里就有歧义，如果是转发到当前控制器方法就有死循环的问题，如果不是就没有问题，直接渲染视图就可以了

        // InternalResourceViewResolver当发现有这种前缀时，直接实例化InternalResourceView
        // 见UrlBasedViewResolver.createView，实例化时没有调用setPreventDispatchLoop方法，
        // 也就是preventDispatchLoop使用默认值false （意思不阻止）
        // 但是控制器方法返回的视图名中如果没有2个特殊的前缀，就会调用createView方法，
        // createView会间接调用InternalResourceViewResolver.buildView方法，
        // buildView方法有调用setPreventDispatchLoop,设置了preventDispatchLoop为true
        // 所以，如果配置类这样配置registry.jsp("", "");访问/c就会报循环视图异常
        // 配置类这样配置registry.jsp("/WEB-INF/views/", ".jsp")，访问/c就不会报异常

        //像这样配置registry.jsp("/WEB-INF/views/", ".jsp")之后，
        // /d(就是上面的defaultView方法）不报循环视图是因为：
        // 1。默认视图名是当前请求地址，
        // 2。视图解析器解析之后视图名是/WEB-INF/views/d.jsp
        // 3.这个视图名与当前请求地址不是一样的，所以不报循环视图异常，见InternalResourceView.prepareForRendering()
        return "c";
    }

    @RequestMapping("/e")
    public String e() {
        //不管配置类这样配置registry.jsp("/WEB-INF/views/", ".jsp"),
        // 还是这样配置registry.jsp("", "")
        // 访问/e都会报stackoverflowerror异常
        // 原因就是有前缀---> 直接实例化InternalResourceView，并没有设置阻止分派循环
        // --->处理后，转发到/e --->又回到这个请求处理方法
        return "forward:e";
    }

    //================circular view 结论========================
    // 1.有2个特殊前缀，不设置阻止分派循环，没有前缀会设置阻止分派循环
    // 2.不阻止分派循环的情况下，真的发生了分派循环就会报堆栈溢出异常，见案例/e地址
    // 3.设置了阻止分派循环，真的发生分派循环就报循环视图异常的错误，而不是堆栈溢出，见/d地址案例
}
